/*
 * 
 *  This file is part of Sourceprojects.org Lycia Copyright 2010 noctarius
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * 
 */
package org.sourceprojects.lycia.internal;

import java.io.InputStream;
import org.sourceprojects.lycia.DefinitionBuilder;
import org.sourceprojects.lycia.LyciaConfigurator;
import org.sourceprojects.lycia.LyciaParser;
import org.sourceprojects.lycia.exceptions.LyciaParsingException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 * Standard implementation of the {@link LyciaParser} interface includes a set
 * of all basic features.
 * 
 * @author noctarius
 * @since 0.0.1
 * 
 * @param <B>
 *            Type of ContextObject
 */
public class LyciaParserImpl<B> extends AndroidCompatibleLyciaParserImpl<B> {
	private boolean validatingSchema = true;

	public LyciaParserImpl() {
		this(null);
	}

	public LyciaParserImpl(final LyciaConfigurator<B> configurator) {
		super(configurator);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.sourceprojects.lycia.XmlParser#transform(java.io.InputStream)
	 */
	@Override
	public Document transform(final InputStream inputStream)
			throws LyciaParsingException {
		try {
			// Create the per parser instances
			final Document document = createReader(inputStream);

			// Create the output document
			final Document transformedDocument = createDocumentBuilder()
					.newDocument();

			final DefinitionBuilder definitionBuilder = new DefinitionBuilderImpl(
					transformedDocument);

			// Start transforming
			for (Node node = document.getFirstChild(); node != null; node = node
					.getNextSibling()) {

				final Node result = transformNode(node, definitionBuilder);

				if (result != null) {
					transformedDocument.appendChild(result);
				}
			}

			return transformedDocument;
		} catch (final Exception e) {
			throw new LyciaParsingException("Transforming failed", e);

		} finally {
			// Explicitly cleanup actual parserContext for threadded use
			if (getParserContext() instanceof InternalParserContext<?>) {
				((InternalParserContext<?>) getParserContext())
						.setContextUtils(new ParserContextUtils());
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.sourceprojects.lycia.XmlParser#isValidatingSchema()
	 */
	@Override
	public boolean isValidatingSchema() {
		return validatingSchema;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.sourceprojects.lycia.XmlParser#setValidatingSchema(boolean)
	 */
	@Override
	public void setValidatingSchema(final boolean validatingSchema) {
		this.validatingSchema = validatingSchema;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "LyciaParserImpl [configurator=" + getConfigurator()
				+ ", errorHandler=" + getErrorHandler() + ", expirationTime="
				+ getCacheExpirationTime() + ", listeners=" + getListeners()
				+ ", parserContext=" + getParserContext() + ", reader="
				+ getReaderInstance() + ", readerClass=" + getReader()
				+ ", resourceResolver=" + getResourceResolver()
				+ ", validatingSchema=" + validatingSchema + "]";
	}
}
